package com.rpa.server.servicerpaserver.crawler.operate;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.rpa.secure.servicerpasecure.common.constant.MessageConstant;
import com.rpa.secure.servicerpasecure.common.constant.ParameterConstant;
import com.rpa.secure.servicerpasecure.common.constant.UrlConstant;
import com.rpa.secure.servicerpasecure.common.exception.TaskException;
import com.rpa.secure.servicerpasecure.common.util.CurrentTeacherInfoUtil;
import com.rpa.server.servicerpaserver.crawler.entity.Active;
import com.rpa.server.servicerpaserver.crawler.entity.Clazz;
import com.rpa.server.servicerpaserver.crawler.entity.User;
import com.rpa.server.servicerpaserver.crawler.entity.dto.ActiveDto;
import com.rpa.server.servicerpaserver.crawler.service.ActiveService;
import com.rpa.server.servicerpaserver.crawler.service.UserService;
import com.rpa.server.servicerpaserver.util.CookieSerialize;
import com.rpa.server.servicerpaserver.util.WebDriverUtil;
import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName ActiveOperate
 * @Description TODO
 * @Author 86152
 * @Date 2025/1/27 15:24
 * @Version 1.0
 **/
@Slf4j
@Component
public class ActiveOperate {
    @Autowired
    private CookieSerialize cookieSerialize;
    @Autowired
    private UserService uerService;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private ActiveService activeService;

    @Async("activeTaskExecutor")
    public CompletableFuture<Boolean>  getActive(ActiveDto activeDto) {
        log.info("获取签到信息");

        // 校验用户是否存在
        User user = uerService.getById(activeDto.getAccountId());
        if (user == null) {
            throw new TaskException(MessageConstant.NO_USER);
        }
        Map stringObjectMap = BeanUtil.beanToMap(activeDto);

        // 调用异步方法获取班级id
        CompletableFuture<List<Map>> classIdsFuture = this.getActiveList(stringObjectMap);

        // 异步任务处理，等待结果
        classIdsFuture.thenAccept(classIds -> {
            if (CollUtil.isEmpty(classIds)) {
                log.error(MessageConstant.SIGN_NULL);
            }
            classIds.forEach(classId -> {
                Map objectObjectHashMap = new HashMap<>() {{
                    putAll(stringObjectMap);
                    putAll(classId);
                }};
                handleSingleClass(objectObjectHashMap);
            });

        }).exceptionally(ex -> {
            log.error("处理签到信息时发生异常", ex);
            return null;
        });

        return CompletableFuture.completedFuture(true); // 这里可以返回处理的状态，如果有需要
    }

    @Async("activeListTaskExecutor")
    public CompletableFuture<List<Map>> getActiveList(Map map) {
        ChromeOptions options = new ChromeOptions();
        WebDriverUtil.setupWebDriver(options);
        ChromeDriver chromeDriver = null;
        List<Map> arrayList = new ArrayList<>();
        String accountId = MapUtil.getStr(map, "accountId", "");
        String courseId = MapUtil.getStr(map, "courseId", "");
        String classId = MapUtil.getStr(map, "classId", "");
        try {
            chromeDriver = new ChromeDriver(options);
            cookieSerialize.goFZF(accountId+"ACTIVE", ParameterConstant.ROUTE_WIDGET, chromeDriver);
            chromeDriver.get(StrUtil.format(UrlConstant.ACTIVE_LIST, cookieSerialize.getCookieValue(accountId, ParameterConstant.FID), courseId,classId,ParameterConstant.TWO,cookieSerialize.getCookieValue(accountId, ParameterConstant.UID)));
            cookieSerialize.delAfterSaveCookies(accountId+"ACTIVE", chromeDriver.manage().getCookies());
            arrayList = WebDriverUtil.getWebDriverDateForName(chromeDriver,"activeList");
        } catch (Exception e) {
            log.error("获取班级签到信息失败", e);
            throw new TaskException(MessageConstant.GET_SIGN_ERROR);
        } finally {
            if (chromeDriver != null) {
                chromeDriver.quit();
            }
        }
        return CompletableFuture.completedFuture(arrayList);
    }
    @Async("activeDetailTaskExecutor")
    public List<Active> getActiveDetail(Map map) {
        ChromeOptions options = new ChromeOptions();
        WebDriverUtil.setupWebDriver(options);
        ChromeDriver chromeDriver = null;
        List<Active> arrayList = new ArrayList<>();
        String accountId = MapUtil.getStr(map, "accountId", "");
        String activeId = MapUtil.getStr(map, "activeId", "");
        String courseId = MapUtil.getStr(map, "courseId", "");
        String classId = MapUtil.getStr(map, "classId", "");
        String endTime = MapUtil.getStr(map, "endTime", "");
        try {
            chromeDriver = new ChromeDriver(options);
            cookieSerialize.goFZF(accountId+"ACTIVE", ParameterConstant.ROUTE_WIDGET, chromeDriver);
            chromeDriver.get(StrUtil.format(UrlConstant.ACTIVE_DETAIL, activeId,classId,courseId,cookieSerialize.getCookieValue(accountId, ParameterConstant.FID)));
            cookieSerialize.delAfterSaveCookies(accountId+"ACTIVE", chromeDriver.manage().getCookies());
            List<Map> weiqianList = WebDriverUtil.getWebDriverDateForName(chromeDriver,"weiqianList");
            List<Map> yiqianList = WebDriverUtil.getWebDriverDateForName(chromeDriver,"yiqianList");
            List<Map> webDriverDate = new ArrayList<>() {{
                addAll(weiqianList);
                addAll(yiqianList);
            }};
            webDriverDate.forEach(map1 -> {
                Active active = new Active();
                active.setActiveId(activeId);
                active.setClazzId(classId);
                active.setCourseId(courseId);
                active.setAccountId(accountId);
                active.setUserId(MapUtil.getStr(map1, "uid", ""));
                active.setUserName(MapUtil.getStr(map1, "name", ""));
                active.setSignStatus(MapUtil.getInt(map1, "status", -1));
                active.setSignTime(MapUtil.getStr(map1, "submittime", ""));
                active.setActiveStatus(2);
                active.setEndTime(endTime);
                arrayList.add(active);
            });
        }catch (Exception e) {
            log.error("获取班级签到信息失败", e);
            throw new TaskException(MessageConstant.GET_SIGN_ERROR);
        }finally {
            if (chromeDriver != null) {
                chromeDriver.quit();
            }
        }
        return arrayList;
    }
    @Transactional
    public void handleSingleClass(Map objectObjectHashMap) {
        List<Active> classNameList = this.getActiveDetail(objectObjectHashMap);
        if (CollUtil.isEmpty(classNameList)) {
           log.error(MapUtil.getStr(objectObjectHashMap, "activeId")+"活动详情为空");
        }
        // 批量更新班级信息
        RLock lock = redissonClient.getLock(objectObjectHashMap.get("activeId").toString());
        try{
            if (lock.tryLock(10, 30, TimeUnit.SECONDS)) {
                this.deleteActive(objectObjectHashMap);
                activeService.saveBatch(classNameList);
            }else{
                log.error("获取锁失败");
            }
        }catch (InterruptedException e) {
            log.error("获取锁失败", e);
        }finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    public Boolean deleteActive(Map objectObjectHashMap) {
        LambdaUpdateWrapper<Active> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(Active::getActiveId,MapUtil.getStr(objectObjectHashMap, "activeId", ""));
        return activeService.remove(lambdaUpdateWrapper);
    }
}
